package com.lp.common.poster;

import com.lp.common.exception.BaseException;
import com.lp.common.exception.ErrorCodeEnum;
import com.lp.common.poster.core.impl.PosterDefaultImpl;
import com.lp.common.poster.entity.*;
import com.lp.common.wechat.WechatService;
import lombok.Builder;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

import static com.lp.common.constant.CategoryConstant.*;

/**
 * @program: biz
 * @description:
 * @author: Ke.Song
 * @since: 2024-04-04 22:04:55
 */
@Slf4j
@Service
public class PosterService {

    @Value("${ali.oss.bucketHost}")
    private String bucketHost;

    @Value("${ali.oss.posterPath}")
    private String posterPath;

    @Value("${ali.oss.fontPath}")
    private String fontPath;

    @Value("${ali.oss.headPath}")
    private String headPath;

    @Value("${wx.indexPath}")
    private String indexPath;

    private Font defaultFont;

    @Autowired
    private WechatService wxService;

    public static final String GRADUATION_CODE = "Graduation";

    public static final String CLASS_NOTICE = "ClassNotice";

    /**
     * 初始化字体
     */
    public void init() {
        try {
            defaultFont = Font.createFont(Font.TRUETYPE_FONT,
                    new URL(this.bucketHost + this.fontPath + "PingFang.ttc").openStream());
        } catch (FontFormatException | IOException e) {
            log.info("画布：初始化字体失败，错误信息：{}", e.getMessage());
            throw new BaseException(ErrorCodeEnum.FAILED);
        }
    }

    @SneakyThrows
    public Resource draw(PosterParams params) {
        Resource data = null;

        BasePoster entity = null;
        BufferedImage image = null;
        File qrCode = wxService.getQrCode(params.getQrCodeScene() == null ? "scene" : params.getQrCodeScene(),
                params.getQrCodePage() == null ? indexPath : params.getQrCodePage());
        if (qrCode != null) {
            params.setQrCode(ImageIO.read(qrCode));
        }
        if (!params.getType().equals(CODE_TRAINING)) {
            params.setHeadImage(ImageIO.read(new URL(params.getHeadImageUrl() != null ? params.getHeadImageUrl() :
                    bucketHost + headPath + "default_image.png")));
        }

        switch (params.getType()) {
            case CODE_READING:
                if (params.getBackgroundImage() == null) {
                    params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "reading_3x.png")));
                }
                if (params.getBookImageUrl() != null) {
                    params.setBookImage(ImageIO.read(new URL(params.getBookImageUrl())));
                }
                entity = drawReadingPoster(params);
                break;
            case CODE_STORY:
                if (params.getBackgroundImage() == null) {
                    params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "story_3x.png")));
                }
                entity = drawStoryPoster(params);
                break;
            case CODE_FAMOUS_REMARK:
                if (params.getBackgroundImage() == null) {
                    params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "famous_rem_3x.png")));
                }
                entity = drawFamousRemPoster(params);
                break;
            case GRADUATION_CODE:
                if (params.getBackgroundImage() == null) {
                    params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "graduation_x2.png")));
                }
                entity = drawGraduationPoster(params);
                break;
            case CODE_TRAINING, CODE_COURSE:
                if (params.getBackgroundImage() == null) {
                    params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "train_3x.png")));
                }
                if (params.getBookImageUrl() != null) {
                    params.setBookImage(ImageIO.read(new URL(params.getBookImageUrl())));
                }
                entity = drawTrainPoster(params);
                break;
            case CLASS_NOTICE:
                if (params.getBackgroundImage() == null) {
                    params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "class_notice_3x.png")));
                }
                entity = drawClassNoticePoster(params);
                break;
            default:
                break;
        }

        if (entity != null) {
            data = generateResource(entity);
        }
        log.info("画布：海报生成成功 ");
        return data;
    }

    @SneakyThrows
    public Resource draw(PosterStudyParams params) {
        File qrCode = wxService.getQrCode(params.getQrCodeScene() == null ? "scene" : params.getQrCodeScene(),
                params.getQrCodePage() == null ? indexPath : params.getQrCodePage());
        if (qrCode != null) {
            params.setQrCode(ImageIO.read(qrCode));
        }
        if (params.getBackgroundImage() == null) {
            params.setBackgroundImage(ImageIO.read(new URL(bucketHost + posterPath + "study_3x.png")));
        }
        params.setHeadImage(ImageIO.read(new URL(params.getHeadImageUrl() != null ? params.getHeadImageUrl() :
                bucketHost + headPath + "default_image.png")));
        BasePoster entity = drawStudyPoster(params);
        Resource data = generateResource(entity);
        log.info("画布：海报生成成功");
        return data;
    }

    @SneakyThrows
    private Resource generateResource(BasePoster entity) {
        Resource data = null;
        // 创建海报生成器
        PosterDefaultImpl<BasePoster> poster = new PosterDefaultImpl<>();
        // 设置默认字体库  /安装用到的全部字体库（支持传多个）
        if (defaultFont == null) {
            init();
        }
        poster.defaultFont(defaultFont);
        // 生成海报
        BufferedImage image = poster.annotationDrawPoster(entity).draw(null);
        if (image != null) {
            // 将图片生成base64
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ImageIO.write(image, "png", stream);
            data = new ByteArrayResource(stream.toByteArray());
        }
        return data;
    }

    /**
     * 共读会
     * @return 结果
     */
    private BasePoster drawReadingPoster(PosterParams params) {
        ReadingPoster readingPoster = new ReadingPoster();
        readingPoster.setBackgroundImage(params.getBackgroundImage());
        readingPoster.setHeadImage(params.getHeadImage());
        readingPoster.setNickName(params.getNickName());
        readingPoster.setName(params.getName());
        readingPoster.setContent(params.getContent());
        readingPoster.setBookImage(params.getBookImage());
        readingPoster.setQrCode(params.getQrCode());
        return readingPoster;
    }

    /**
     * 故事
     * @return 结果
     */
    private BasePoster drawStoryPoster(PosterParams params) {
        StoryPoster storyPoster = new StoryPoster();
        storyPoster.setBackgroundImage(params.getBackgroundImage());
        storyPoster.setHeadImage(params.getHeadImage());
        storyPoster.setNickName(params.getNickName());
        storyPoster.setName(params.getName());
        storyPoster.setContent(params.getContent());
        storyPoster.setQrCode(params.getQrCode());
        return storyPoster;
    }

    /**
     * 名人名言
     * @return 结果
     */
    private BasePoster drawFamousRemPoster(PosterParams params) {
        FamousRemPoster famousRemPoster = new FamousRemPoster();
        famousRemPoster.setBackgroundImage(params.getBackgroundImage());
        famousRemPoster.setHeadImage(params.getHeadImage());
        famousRemPoster.setNickName(params.getNickName());
        famousRemPoster.setContent(params.getContent());
        famousRemPoster.setQrCode(params.getQrCode());
        famousRemPoster.setAuthor(params.getAuthor());
        return famousRemPoster;
    }

    private BasePoster drawGraduationPoster(PosterParams params) {
        GraduationPoster graduationPoster = new GraduationPoster();
        graduationPoster.setBackgroundImage(params.getBackgroundImage());
        graduationPoster.setHeadImage(params.getHeadImage());
        graduationPoster.setNickName(params.getNickName());
        graduationPoster.setContent(params.getContent());
        graduationPoster.setSubtitle(params.getSubtitle());
        return graduationPoster;
    }

    private BasePoster drawTrainPoster(PosterParams params) {
        TrainPoster trainPoster = new TrainPoster();
        trainPoster.setBackgroundImage(params.getBackgroundImage());
        trainPoster.setContent(params.getContent());
        trainPoster.setBookImage(params.getBookImage());
        trainPoster.setName(params.getName());
        trainPoster.setPrice(params.getPrice() == null ? null : "￥" + params.getPrice());
        trainPoster.setContent(params.getContent());
        trainPoster.setQrCode(params.getQrCode());
        return trainPoster;
    }

    private BasePoster drawStudyPoster(PosterStudyParams params) {
        StudyPoster studyPoster = new StudyPoster();
        studyPoster.setBackgroundImage(params.getBackgroundImage());
        studyPoster.setHeadImage(params.getHeadImage());
        studyPoster.setNickName(params.getNickName());
        studyPoster.setQrCode(params.getQrCode());
        studyPoster.setTodayTime(params.getTodayTime());
        studyPoster.setTodayTimeUnit(params.getTodayTimeUnit());
        studyPoster.setOnlineTime(params.getOnlineTime());
        studyPoster.setOnlineTimeUnit(params.getOnlineTimeUnit());
        studyPoster.setReadingNum(params.getReadingNum());
        studyPoster.setReadingNumUnit(params.getReadingNumUnit());
        studyPoster.setClassNum(params.getClassNum());
        studyPoster.setClassNumUnit(params.getClassNumUnit());
        studyPoster.setWordNum(params.getWordNum());
        studyPoster.setWordNumUnit(params.getWordNumUnit());
        studyPoster.setStoryNum(params.getStoryNum());
        studyPoster.setStoryNumUnit(params.getStoryNumUnit());
        studyPoster.setSpeechNum(params.getSpeechNum());
        studyPoster.setSpeechNumUnit(params.getSpeechNumUnit());
        return studyPoster;
    }

    private BasePoster drawClassNoticePoster(PosterParams params) {
        ClassNoticePoster noticePoster = new ClassNoticePoster();
        noticePoster.setBackgroundImage(params.getBackgroundImage());
        noticePoster.setNickName(params.getNickName());
        noticePoster.setClassName(params.getClassName());
        noticePoster.setQrCode(params.getQrCode());
        noticePoster.setDate(params.getDate());
        return noticePoster;
    }

    @Data
    @Builder
    public static class PosterParams {

        /**
         * 背景图
         */
        BufferedImage backgroundImage;

        /**
         * 书本竖图
         */
        BufferedImage bookImage;

        /**
         * 二维码
         */
        BufferedImage qrCode;

        /**
         * 二维码Scene
         */
        String qrCodeScene;

        /**
         * 二维码Page
         */
        String qrCodePage;

        /**
         * 头像
         */
        BufferedImage headImage;

        /**
         * 头像
         */
        String headImageUrl;

        /**
         * 书本竖图
         */
        String bookImageUrl;

        /**
         * 标题
         */
        String name;

        /**
         * 内容
         */
        String content;

        /**
         * 昵称
         */
        String nickName;

        /**
         * 作者
         */
        String author;

        /**
         * 价格
         */
        String price;

        String type;

        String subtitle;

        /**
         * 班级名
         */
        String className;

        String date;
    }

    @Data
    public static class PosterStudyParams {

        /**
         * 背景图
         */
        BufferedImage backgroundImage;

        /**
         * 二维码
         */
        BufferedImage qrCode;


        /**
         * 二维码Scene
         */
        String qrCodeScene;

        /**
         * 二维码Page
         */
        String qrCodePage;

        /**
         * 头像
         */
        String headImageUrl;

        /**
         * 头像
         */
        BufferedImage headImage;

        /**
         * 昵称
         */
        String nickName;

        /**
         * 今日学习
         */
        String todayTime;

        /**
         * 今日学习单位
         */
        String todayTimeUnit;

        /**
         * 累计学习
         */
        String onlineTime;

        /**
         * 累计学习单位
         */
        String onlineTimeUnit;

        /**
         * 听书单位
         */
        String readingNumUnit;

        /**
         * 听书
         */
        String readingNum;

        /**
         * 学习课程
         */
        String classNum;

        /**
         * 学习课程单位
         */
        String classNumUnit;

        /**
         * 创作
         */
        String wordNum;

        /**
         * 创作单位
         */
        String wordNumUnit;

        /**
         * 听故事
         */
        String storyNum;

        /**
         * 听故事单位
         */
        String storyNumUnit;

        /**
         * 公众演说
         */
        String speechNum;

        /**
         * 公众演说单位
         */
        String speechNumUnit;

        public static PosterStudyParams builder() {
            return new PosterStudyParams();
        }

        public PosterStudyParams nickName(String nickName) {
            this.nickName = nickName;
            return this;
        }

        public PosterStudyParams headImageUrl(String headImageUrl) {
            this.headImageUrl = headImageUrl;
            return this;
        }

        public PosterStudyParams qrCodePage(String qrCodePage) {
            this.qrCodePage = qrCodePage;
            return this;
        }

        public PosterStudyParams qrCodeScene(String qrCodeScene) {
            this.qrCodeScene = qrCodeScene;
            return this;
        }

        public PosterStudyParams todayTime(Integer todayTime) {
            if (todayTime != null) {
                TimeUnit unit = TimeUnit.SECONDS;
                long days = unit.toDays(todayTime);
                long hours = unit.toHours(todayTime) % 24;
                long minutes = unit.toMinutes(todayTime) % 60;
                if (days > 0) {
                    this.todayTime = String.valueOf(days);
                    this.todayTimeUnit = "天";
                } else if (hours > 0) {
                    this.todayTime = String.valueOf(hours);
                    this.todayTimeUnit = "小时";
                } else if (minutes > 0) {
                    this.todayTime = String.valueOf(minutes);
                    this.todayTimeUnit = "分钟";
                } else {
                    this.todayTime = String.valueOf(todayTime);
                    this.todayTimeUnit = "秒";
                }
            } else {
                this.todayTime = String.valueOf(0);
            }
            return this;
        }

        public PosterStudyParams onlineTime(Integer onlineTime) {
            if (onlineTime != null) {
                TimeUnit unit = TimeUnit.SECONDS;
                long days = unit.toDays(onlineTime);
                long hours = unit.toHours(onlineTime) % 24;
                long minutes = unit.toMinutes(onlineTime) % 60;
                if (days > 0) {
                    this.onlineTime = String.valueOf(days);
                    this.onlineTimeUnit = "天";
                } else if (hours > 0) {
                    this.onlineTime = String.valueOf(hours);
                    this.onlineTimeUnit = "小时";
                } else if (minutes > 0) {
                    this.onlineTime = String.valueOf(minutes);
                    this.onlineTimeUnit = "分钟";
                } else {
                    this.onlineTime = String.valueOf(onlineTime);
                    this.onlineTimeUnit = "秒";
                }
            } else {
                this.onlineTime = String.valueOf(0);
            }
            return this;
        }

        public PosterStudyParams readingNum(Integer readingNum) {
            if (readingNum != null) {
                this.readingNum = String.valueOf(readingNum);
            } else {
                this.readingNum = String.valueOf(0);
            }
            this.readingNumUnit = "本";
            return this;
        }

        public PosterStudyParams classNum(Integer classNum) {
            if (classNum != null) {
                this.classNum = String.valueOf(classNum);
            } else {
                this.classNum = String.valueOf(0);
            }
            this.classNumUnit = "门";
            return this;
        }

        public PosterStudyParams wordNum(Integer wordNum) {
            if (wordNum != null) {
                if (wordNum < 10000) {
                    this.wordNum = String.valueOf(wordNum);
                    this.wordNumUnit = "字";
                } else {
                    this.wordNum = String.format("%.1f", wordNum / 10000.0);
                    this.wordNumUnit = "万字";
                }
            } else {
                this.wordNum = String.valueOf(0);
            }
            return this;
        }

        public PosterStudyParams storyNum(Integer storyNum) {
            if (storyNum != null) {
                this.storyNum = String.valueOf(storyNum);
            } else {
                this.storyNum = String.valueOf(0);
            }
            this.storyNumUnit = "篇";
            return this;
        }

        public PosterStudyParams speechNum(Integer speechNum) {
            if (speechNum != null) {
                this.speechNum = String.valueOf(speechNum);
            } else {
                this.speechNum = String.valueOf(0);
            }
            this.speechNumUnit = "次";
            return this;
        }
    }
}
